#ifndef _CDSLIB_GLOBALS_H
#define _CDSLIB_GLOBALS_H

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>

/* uint512_t definition used by genericHash */
typedef struct {
    uint64_t _[8];
} uint512_t;

#define _MIN(_x, _y) ((_x) < (_y)) ? (_x) : (_y)
#define _MAX(_x, _y) ((_x) < (_y)) ? (_y) : (_x)

#define _VECTOR_START_CAPACITY 10
#define _VECTOR_GROW_FACTOR    1.5
#define _VECTOR_SHRINK_FACTOR  2.0

#define _HASHMAP_START_CAPACITY  10
#define _HASHMAP_MIN_LOAD_FACTOR 0.20
#define _HASHMAP_MAX_LOAD_FACTOR 0.75

#define _TYPE_CHAIN   0
#define _TYPE_LIST    1
#define _TYPE_STACK   2
#define _TYPE_QUEUE   3
#define _TYPE_DEQUE   4

int    __genericCompare(const void *_objectOne, const void *_objectTwo);
size_t __genericHash   (const void *_Object,    const size_t _objectSize);

/* Constructor macros */
#define initList(l)  _initChain(_TYPE_LIST, l)
#define initStack(s) _initChain(_TYPE_STACK, s)
#define initQueue(q) _initChain(_TYPE_QUEUE, q)
#define initDeque(e) _initChain(_TYPE_DEQUE, e)

/* Destructor macros */
#define deleteList(l)  _deleteChain(l)
#define deleteStack(s) _deleteChain(s)
#define deleteQueue(q) _deleteChain(q)
#define deleteDeque(e) _deleteChain(d)

/* Function macros */
#define ListAdd    (l, addThis)           _ChainAdd(l, addThis)
#define ListGet    (l, index)             _ChainGet(l, index)
#define ListSet    (l, index, setThis)    _ChainSet(l, index, setThis)
#define ListInsert (l, index, insertThis) _ChainInsert(l, index, insertThis)
#define ListExtract(l, index)             _ChainExtract(l, index)

#define StackPush(s, pushThis) _ChainPushFront(s, pushThis)
#define StackPop (s)           _ChainPopFront (s)

#define QueuePush(q, pushThis) _ChainPushFront(q, pushThis)
#define QueuePop (q)           _ChainPopBack  (q)

#define DequePushFront(d, pushThis) _ChainPushFront(d, pushThis)
#define DequePushBack (d, pushThis) _ChainPushBack (d, pushThis)
#define DequePopFront (d)           _ChainPopFront (d)
#define DequePopBack  (d)           _ChainPopBack  (d)

/* Bounds checking macros */
#define _indexError(_index) fprintf(stderr, \
                                    "Error: Index %lu out of bounds\n", \
                                    _index);
#define _boundsCheck(_x, _index) ((_x->length > _index) ? 1 : 0)

#endif
